package app.game;


import app.engine.component.AbstractSearchEngine;
import app.engine.mc.MCTreeSearchEngine;
import app.game.enums.Chess;
import app.game.enums.Direction;
import app.ui.Config;

import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;


/**
 * @Description 棋盘类
 * @Date 2022/4/10 17:20
 * @Created by LYP
 */
public class ChessBoard implements Config {

    private Chess[][] chessBoard = new Chess[BOARD_LINE][BOARD_LINE];

    private Chess nowChess;

    private Graphics graphics;

    private JLabel nowChesslabel;

    private AbstractSearchEngine searchEngine;

    private int step;

    private List<ChessPoint> cpList;

    public static final int BOARD_LEFT = BOARD_MARGIN;
    public static final int BOARD_RIGHT = BOARD_MARGIN + BOARD_LINE * CHESS_SIZE;
    public static final int BOARD_UP = BOARD_MARGIN + MENU_SIZE;
    public static final int BOARD_DOWN = BOARD_MARGIN + MENU_SIZE + BOARD_LINE * CHESS_SIZE;
    public static final int BOARD_SIZE = BOARD_LINE * CHESS_SIZE;
    /**
     * 默认初始化为空
     */
    public ChessBoard(Graphics g){
        init();
        this.graphics = g;
        searchEngine = new MCTreeSearchEngine();
    }

    public void init() {
        for (int i = 0; i < BOARD_LINE; i++) {
            for (int j = 0; j < BOARD_LINE; j++) {
                chessBoard[i][j] = Chess.EMPTY;
            }
        }
        nowChess = Chess.BLACK_CHESS;
        step = 1;
        cpList = new ArrayList<>();
    }

    public void drawChessBoard() {
        graphics.setColor(Color.ORANGE);
        graphics.fillRect(BOARD_LEFT, BOARD_UP, BOARD_SIZE, BOARD_SIZE);
        graphics.setColor(Color.BLACK);
        for (int i = 0; i < BOARD_LINE; i++) {
            graphics.drawLine(
                    BOARD_LEFT + CHESS_SIZE / 2,
                    BOARD_UP + CHESS_SIZE / 2 + (i * CHESS_SIZE),
                    BOARD_RIGHT - CHESS_SIZE / 2,
                    BOARD_UP + CHESS_SIZE / 2 + (i * CHESS_SIZE)
            );
            graphics.drawLine(
                    BOARD_LEFT + CHESS_SIZE / 2 + (i * CHESS_SIZE),
                    BOARD_UP + CHESS_SIZE / 2,
                    BOARD_LEFT + CHESS_SIZE / 2 + (i * CHESS_SIZE),
                    BOARD_DOWN - CHESS_SIZE / 2
            );
        }
        for (int i = 0; i < BOARD_LINE; i++) {
            for (int j = 0; j < BOARD_LINE; j++) {
                drawChess(chessBoard[i][j], j, i);
            }
        }
        nowChesslabel.setText("当前行棋方：" + nowChess.getName());
    }

    private void drawChess(Chess chess, int x, int y) {
        switch (chess) {
            case BLACK_CHESS:
                graphics.setColor(Color.BLACK);
                graphics.fillOval(
                        BOARD_LEFT + (x * CHESS_SIZE),
                        BOARD_UP + (y * CHESS_SIZE),
                        CHESS_SIZE,
                        CHESS_SIZE
                );
                break;
            case WHITH_CHESS:
                graphics.setColor(Color.WHITE);
                graphics.fillOval(
                        BOARD_LEFT + (x * CHESS_SIZE),
                        BOARD_UP + (y * CHESS_SIZE),
                        CHESS_SIZE,
                        CHESS_SIZE
                );
                break;
        }
    }

    public boolean comPutChess(Chess comChess) {
        ChessPoint chessPoint = searchEngine.search(chessBoard, comChess, step, cpList);
        setChess(chessPoint.getX(), chessPoint.getY(), nowChess);
        drawChessBoard();
        if (isEnd(chessPoint.getX(), chessPoint.getY())) {
            return true;
        }
        changeNowChess();
        return false;
    }

    public boolean isEnd(int x, int y){
        ChessPoint thisPoint = new ChessPoint(x, y);
        Direction[] directions = Direction.values();
        for (Direction direction: directions) {
            int count = 1;
            ChessPoint point = thisPoint.getNext(direction, 1);
            while (point.isOnTable() && chessBoard[point.getX()][point.getY()] == nowChess) {
                count++;
                point.next(direction, 1);
            }
            point = thisPoint.getNext(direction, -1);
            while (point.isOnTable() && chessBoard[point.getX()][point.getY()] == nowChess) {
                count++;
                point.next(direction, -1);
            }
            if (count >= 5) {
                return true;
            }
        }
        return false;
    }

    public Chess getChess(int x, int y) {
        return chessBoard[x][y];
    }

    public void setChess(int x, int y, Chess c) {
        chessBoard[x][y] = c;
        cpList.add(new ChessPoint(x, y));
    }

    public Chess getNowChess() {
        return nowChess;
    }

    public void changeNowChess() {
        if (nowChess == Chess.BLACK_CHESS) {
            nowChess = Chess.WHITH_CHESS;
        } else {
            nowChess = Chess.BLACK_CHESS;
        }
        nowChesslabel.setText("当前行棋方：" + nowChess.getName());
        step++;
    }

    public JLabel getNowChesslabel() {
        return nowChesslabel;
    }

    public void setNowChesslabel(JLabel nowChesslabel) {
        this.nowChesslabel = nowChesslabel;
    }

    public static Chess[][] copy(Chess[][] chessBoard) {
        Chess[][] copyChessBoard = new Chess[BOARD_LINE][BOARD_LINE];
        for (int i = 0; i < BOARD_LINE; i++) {
            for (int j = 0; j < BOARD_LINE; j++) {
                copyChessBoard[i][j] = chessBoard[i][j];
            }
        }
        return copyChessBoard;
    }
}
